window.onload = function() {
  /**
   * 1、能发起请求
   * 2、能拦截请求
   * 3、能取消请求
   */
  class Axios {
    constructor(config) {
      this.defaults = config; // 默认配置
      this.interceptors = {
        // 拦截器
        request: new InterceptorsManager(),
        response: new InterceptorsManager()
      };
    }
    get(getConfig) {
      return this.request(getConfig);
    }
    post(postConfig) {
      return this.request(postConfig, 'post');
    }
    request(requestConfig, method = 'get') {
      let configObj = { method };
      if (typeof requestConfig === 'string') {
        configObj.url = requestConfig;
      } else {
        configObj = Object.assign({}, requestConfig, configObj);
      }
      let chains = [dispatchRequest, undefined];
      this.interceptors.request.handlers.forEach((ls) => {
        chains.unshift(ls.fulfilled, ls.rejected);
      });
      this.interceptors.response.handlers.forEach((ls) => {
        chains.push(ls.fulfilled, ls.rejected);
      });
      let len = chains.length;
      let idx = 0;
      let promise = Promise.resolve(configObj);
      while (idx < len) {
        // 先使用，再 +1
        promise = promise.then(chains[idx++], chains[idx++]);
      }
      return promise;
    }
  }
  class InterceptorsManager {
    handlers = [];
    use(fulfilled, rejected) {
      this.handlers.push({
        fulfilled,
        rejected
      });
    }
    clear() {
      this.handlers = [];
    }
  }
  async function dispatchRequest(config) {
    let res = await xhrAdaptor(config);
    return JSON.parse(res.response);
  }
  function xhrAdaptor(config) {
    return new Promise((resolve, reject) => {
      let xhr = new XMLHttpRequest();
      xhr.open(config.method, config.url);
      xhr.onreadystatechange = function() {
        if (xhr.readyState === 4) {
          let { status, statusText, response } = xhr;
          if (status >= 200 && status < 300) {
            resolve({
              config,
              status,
              statusText,
              request: xhr,
              response,
              headers: xhr.getAllResponseHeaders()
            });
          } else {
            reject({
              config,
              status,
              statusText,
              request: xhr,
              response: '请求出错了！',
              headers: xhr.getAllResponseHeaders()
            });
          }
        }
      };
      if (config.cancelToken) {
        config.cancelToken.promise.then(() => {
          xhr.abort();
        });
      }
      xhr.send();
    });
  }
  function createInstance(config = {}) {
    let context = new Axios(config);
    let instance = Axios.prototype.request.bind(context);
    instance.create = function(customConfig) {
      return createInstance(Object.assign({}, config, customConfig));
    };
    // 获取实例属性
    Object.keys(context).forEach((key) => {
      instance[key] = context[key];
    });
    // 获取原型方法
    Object.getOwnPropertyNames(Axios.prototype).forEach((key) => {
      instance[key] = Axios.prototype[key].bind(context);
    });
    return instance;
  }
  class CancelToken {
    constructor(excutor) {
      this.resolvePromise = null;
      this.promise = new Promise((resolve) => {
        this.resolvePromise = resolve;
      });
      excutor(() => {
        this.resolvePromise && this.resolvePromise();
      });
    }
  }
  let cancel = null; // 取消请求的回调函数
  const axios = createInstance();
  // 请求拦截器(因为请求拦截器是unshift进入chains的，所以后设置的先执行)
  axios.interceptors.request.use(
    (config) => {
      console.log('请求拦截器fulfilled22');
      return config;
    },
    (err) => {
      console.log('请求拦截器rejected22');
      return Promise.reject(err);
    }
  );
  axios.interceptors.request.use(
    (config) => {
      console.log('请求拦截器fulfilled11');
      return config;
    },
    (err) => {
      console.log('请求拦截器rejected11');
      return Promise.reject(err);
    }
  );
  // 响应拦截器
  axios.interceptors.response.use(
    (res) => {
      console.log('响应拦截器fulfilled11');
      return res;
    },
    (err) => {
      console.log('响应拦截器rejected11');
      return Promise.reject(err);
    }
  );
  axios.interceptors.response.use(
    (res) => {
      console.log('响应拦截器fulfilled22');
      return res;
    },
    (err) => {
      console.log('响应拦截器rejected22');
      return Promise.reject(err);
    }
  );
  // 获取按钮dom
  let btns = document.querySelectorAll('button');
  // 点击发起请求
  btns[0].onclick = function() {
    axios({
      url: 'http://localhost:3000/goodsList',
      cancelToken: new CancelToken((c) => (cancel = c))
    })
      .then((res) => {
        cancel = null;
        if (res && res.code === 200) {
          console.log('结果为==>', res.data);
        }
      })
      .catch((err) => {
        cancel = null;
        console.log('错误为==>', err);
      });
  };
  // 点击取消请求
  btns[1].onclick = function() {
    console.log('取消请求');
    if (cancel) {
      cancel();
    }
  };
};
